/*
  Copyright (c) 2010
  The Regents of the University of Michigan
  All Rights Reserved

  Permission is granted to use, copy, create derivative works, and
  redistribute this software and such derivative works for any purpose,
  so long as the name of the University of Michigan is not used in
  any advertising or publicity pertaining to the use or distribution
  of this software without specific, written prior authorization. If
  the above copyright notice or any other identification of the
  University of Michigan is included in any copy of any portion of
  this software, then the disclaimer below must also be included.

  This software is provided as is, without representation or warranty
  of any kind either express or implied, including without limitation
  the implied warranties of merchantability, fitness for a particular
  purpose, or noninfringement.  The Regents of the University of
  Michigan shall not be liable for any damages, including special,
  indirect, incidental, or consequential damages, with respect to any
  claim arising out of or in connection with the use of the software,
  even if it has been or is hereafter advised of the possibility of
  such damages.
*/
/*
 *  mojito_serialization.h
 *  DHT
 *
 *  Created by Dhritiman Sagar.
 *
 */

#ifndef MOJITO_SERIALIZATION_H
#define MOJITO_SERIALIZATION_H

#include "mojito_types.h"
#include "mojito_constants.h"
#include "clearview.h"

#include <sys/types.h>
#include <glib.h>


enum HeaderFlags {
	FIREWALLED = 0x01,
	SHUTDOWN = 0x02,
};


struct MojitoHeader {
	uint8_t message_id[MESSAGE_ID_SIZE]; /*Unique to the message*/
	uint8_t f_dht_message; /*A hard coded value (0x44)*/
	version_t version; /*0 for our purpose*/
	uint32_t length; /*Payload length in LITTLE ENDIAN (??) format*/
	enum Action opcode;
	struct Contact contact;
	uint8_t contact_instance_id;
	uint8_t contact_flags;
	uint16_t extended_header_len; /*Usually set to 0 for our purposes*/
};


struct MojitoPingRequestPacket{
	struct MojitoHeader header;
};

struct MojitoPingReplyPacket{
	struct MojitoHeader header;
	struct SocketAddress requester_address; /*Requester's address*/
	struct BigInteger estimated_dht_size; /*Size of the DHT as estimated by responder*/
	
};


struct MojitoStoreRequestPacket{
	struct MojitoHeader header;
	struct SecurityToken st;
	uint8_t count; /*Count of DHTValues that follow*/
	struct DHTValue* values; /*array of values to store*/
};

struct MojitoStoreReplyPacket{
	struct MojitoHeader header;
	uint8_t count;
	struct StatusCode* sc; /*First entry tells whether the KUID was stored*/
	
};


struct MojitoFindNodeRequestPacket{
	struct MojitoHeader header;
	struct kuid_t target_kuid;
};

struct MojitoFindNodeReplyPacket{
	struct MojitoHeader header;
	struct SecurityToken st;
	uint8_t count;
	struct Contact* contacts; /*Array of contacts*/
	
};

struct MojitoFindValueRequestPacket{
	struct MojitoHeader header;
	struct kuid_t primary_key;
	uint8_t count; /*Count of the secondary keys that will follow*/
	struct kuid_t* secondary_keys;
};

struct MojitoFindValueReplyPacket{
	struct MojitoHeader header;
	float request_load;
	uint8_t value_count; /*Count of values that will follow*/
	struct DHTValue* values; /*Array of values*/
	uint8_t secondary_key_count; /*Count of secondary keys that will follow*/
	struct kuid_t* secondary_keys;
};


/*Decoding functions*/
int decode_mojito_request(const char* packet, size_t length, 
						   struct Contact* contact);

int decode_mojito_reply(const char *packet, size_t len,
						struct Contact *contact);

static inline int decode_mojito_header(const char* packet, const char* end,
									   struct MojitoHeader* out);

static inline int decode_mojito_ping_request(const struct MojitoHeader *header,
											 struct MojitoPingRequestPacket* out,
											 const char *packet, const char *end,
											 struct Contact *contact);

int decode_mojito_find_node_request(const struct MojitoHeader *header,
									struct MojitoFindNodeRequestPacket* out,
									const char *packet, const char *end,
									struct Contact *contact);

int decode_mojito_store_request(const struct MojitoHeader *header,
								struct MojitoStoreRequestPacket* out,
								const char *packet, const char *end,
								struct Contact *contact);

int decode_mojito_find_value_request(const struct MojitoHeader *header,
									 struct MojitoFindValueRequestPacket* out,
									 const char *packet, const char *end,
									 struct Contact *contact);

static inline int decode_mojito_ping_reply(const struct MojitoHeader *header,
										   struct MojitoPingReplyPacket* out,
										   const char *packet, const char *end,
										   struct Contact *contact);

int decode_mojito_find_node_reply(const struct MojitoHeader *header,
								  struct MojitoFindNodeReplyPacket* out,
								  const char *packet, const char *end,
								  struct Contact *contact);

int decode_mojito_store_reply(const struct MojitoHeader *header,
							  struct MojitoStoreReplyPacket* out,
							  const char *packet, const char *end,
							  struct Contact *contact);

int decode_mojito_find_value_reply(const struct MojitoHeader *header,
								   struct MojitoFindValueReplyPacket* out,
								   const char *packet, const char *end,
								   struct Contact *contact);






/*Encoding Functions*/
void encode_mojito_ping_request(const struct MojitoPingRequestPacket *packet, char **buf,
                         size_t *buflen);

void encode_mojito_find_node_request(const struct MojitoFindNodeRequestPacket *packet,
                              char **user_buf, size_t *buflen);

void encode_mojito_store_request(const struct MojitoStoreRequestPacket *packet,
										char **user_buf, size_t *buflen);

void encode_mojito_find_value_request(const struct MojitoFindValueRequestPacket *packet,
										char **user_buf, size_t *buflen);

void encode_mojito_ping_reply(const struct MojitoPingReplyPacket *packet, char **buf,
							  size_t *buflen);

void encode_mojito_find_node_reply(const struct MojitoFindNodeReplyPacket *packet,
                            char **buf, size_t *buflen);

void encode_mojito_store_reply(const struct MojitoStoreReplyPacket *packet,
                        char **buf, size_t *buflen);

void encode_mojito_find_value_reply(const struct MojitoFindValueReplyPacket *packet,
								   char **buf, size_t *buflen);





#endif
